home *** CD-ROM | disk | FTP | other *** search
/ Action Games (2008) / akcnihry1.iso / Code RED / codered.exe / Data1.cab / glw_imp.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-08-13  |  13.9 KB  |  616 lines

  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. /*
  21. ** GLW_IMP.C
  22. **
  23. ** This file contains ALL Win32 specific stuff having to do with the
  24. ** OpenGL refresh.  When a port is being made the following functions
  25. ** must be implemented by the port:
  26. **
  27. ** GLimp_EndFrame
  28. ** GLimp_Init
  29. ** GLimp_Shutdown
  30. ** GLimp_SwitchFullscreen
  31. **
  32. */
  33. #include <assert.h>
  34. #include <windows.h>
  35. #include "../ref_gl/r_local.h"
  36. #include "glw_win.h"
  37. #include "winquake.h"
  38.  
  39. static qboolean GLimp_SwitchFullscreen( int width, int height );
  40. qboolean GLimp_InitGL (void);
  41.  
  42. glwstate_t glw_state;
  43.  
  44. extern cvar_t *vid_fullscreen;
  45. extern cvar_t *vid_ref;
  46.  
  47. static qboolean VerifyDriver( void )
  48. {
  49.     char buffer[1024];
  50.  
  51.     strcpy( buffer, qglGetString( GL_RENDERER ) );
  52.     strlwr( buffer );
  53.     if ( strcmp( buffer, "gdi generic" ) == 0 )
  54.         if ( !glw_state.mcd_accelerated )
  55.             return false;
  56.     return true;
  57. }
  58.  
  59. /*
  60. ** VID_CreateWindow
  61. */
  62. #define    WINDOW_CLASS_NAME    "Quake 2"
  63.  
  64. qboolean VID_CreateWindow( int width, int height, qboolean fullscreen )
  65. {
  66.     WNDCLASS        wc;
  67.     RECT            r;
  68.     cvar_t            *vid_xpos, *vid_ypos;
  69.     int                stylebits;
  70.     int                x, y, w, h;
  71.     int                exstyle;
  72.  
  73.     /* Register the frame class */
  74.     wc.style         = 0;
  75.     wc.lpfnWndProc   = (WNDPROC)glw_state.wndproc;
  76.     wc.cbClsExtra    = 0;
  77.     wc.cbWndExtra    = 0;
  78.     wc.hInstance     = glw_state.hInstance;
  79.     wc.hIcon         = 0;
  80.     wc.hCursor       = LoadCursor (NULL,IDC_ARROW);
  81.     wc.hbrBackground = (void *)COLOR_GRAYTEXT;
  82.     wc.lpszMenuName  = 0;
  83.     wc.lpszClassName = WINDOW_CLASS_NAME;
  84.  
  85.     if (!RegisterClass (&wc) )
  86.         Com_Error (ERR_FATAL, "Couldn't register window class");
  87.  
  88.     if (fullscreen)
  89.     {
  90.         exstyle = WS_EX_TOPMOST;
  91.         stylebits = WS_POPUP|WS_VISIBLE;
  92.     }
  93.     else
  94.     {
  95.         exstyle = 0;
  96.         stylebits = WINDOW_STYLE;
  97.     }
  98.  
  99.     r.left = 0;
  100.     r.top = 0;
  101.     r.right  = width;
  102.     r.bottom = height;
  103.  
  104.     AdjustWindowRect (&r, stylebits, FALSE);
  105.  
  106.     w = r.right - r.left;
  107.     h = r.bottom - r.top;
  108.  
  109.     if (fullscreen)
  110.     {
  111.         x = 0;
  112.         y = 0;
  113.     }
  114.     else
  115.     {
  116.         vid_xpos = Cvar_Get ("vid_xpos", "0", 0);
  117.         vid_ypos = Cvar_Get ("vid_ypos", "0", 0);
  118.         x = vid_xpos->value;
  119.         y = vid_ypos->value;
  120.     }
  121.  
  122.     glw_state.hWnd = CreateWindowEx (
  123.          exstyle, 
  124.          WINDOW_CLASS_NAME,
  125.          "Quake 2",
  126.          stylebits,
  127.          x, y, w, h,
  128.          NULL,
  129.          NULL,
  130.          glw_state.hInstance,
  131.          NULL);
  132.  
  133.     if (!glw_state.hWnd)
  134.         Com_Error (ERR_FATAL, "Couldn't create window");
  135.     
  136.     ShowWindow( glw_state.hWnd, SW_SHOW );
  137.     UpdateWindow( glw_state.hWnd );
  138.  
  139.     // init all the gl stuff for the window
  140.     if (!GLimp_InitGL ())
  141.     {
  142.         Com_Printf ("VID_CreateWindow() - GLimp_InitGL failed\n");
  143.         return false;
  144.     }
  145.  
  146.     SetForegroundWindow( glw_state.hWnd );
  147.     SetFocus( glw_state.hWnd );
  148.  
  149.     // let the sound and input subsystems know about the new window
  150.     VID_NewWindow (width, height);
  151.  
  152.     return true;
  153. }
  154.  
  155.  
  156. /*
  157. ** GLimp_SetMode
  158. */
  159. rserr_t GLimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen )
  160. {
  161.     int width, height;
  162.     const char *win_fs[] = { "W", "FS" };
  163.  
  164.     Com_Printf ("Initializing OpenGL display\n");
  165.  
  166.     Com_Printf ("...setting mode %d:", mode );
  167.  
  168.     if ( !VID_GetModeInfo( &width, &height, mode ) )
  169.     {
  170.         Com_Printf( " invalid mode\n" );
  171.         return rserr_invalid_mode;
  172.     }
  173.  
  174.     Com_Printf (" %d %d %s\n", width, height, win_fs[fullscreen] );
  175.  
  176.     // destroy the existing window
  177.     if (glw_state.hWnd)
  178.     {
  179.         GLimp_Shutdown ();
  180.     }
  181.  
  182.     // do a CDS if needed
  183.     if ( fullscreen )
  184.     {
  185.         DEVMODE dm;
  186.  
  187.         Com_Printf ("...attempting fullscreen\n" );
  188.  
  189.         memset( &dm, 0, sizeof( dm ) );
  190.  
  191.         dm.dmSize = sizeof( dm );
  192.  
  193.         dm.dmPelsWidth  = width;
  194.         dm.dmPelsHeight = height;
  195.         dm.dmFields     = DM_PELSWIDTH | DM_PELSHEIGHT;
  196.  
  197.         if ( gl_bitdepth->value != 0 )
  198.         {
  199.             dm.dmBitsPerPel = gl_bitdepth->value;
  200.             dm.dmFields |= DM_BITSPERPEL;
  201.             Com_Printf( "...using gl_bitdepth of %d\n", ( int ) gl_bitdepth->value );
  202.         }
  203.         else
  204.         {
  205.             HDC hdc = GetDC( NULL );
  206.             int bitspixel = GetDeviceCaps( hdc, BITSPIXEL );
  207.  
  208.             Com_Printf ("...using desktop display depth of %d\n", bitspixel );
  209.  
  210.             ReleaseDC( 0, hdc );
  211.         }
  212.  
  213.         Com_Printf ("...calling CDS: " );
  214.         if ( ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) == DISP_CHANGE_SUCCESSFUL )
  215.         {
  216.             *pwidth = width;
  217.             *pheight = height;
  218.  
  219.             gl_state.fullscreen = true;
  220.  
  221.             Com_Printf ("ok\n" );
  222.  
  223.             if ( !VID_CreateWindow (width, height, true) )
  224.                 return rserr_invalid_mode;
  225.  
  226.             return rserr_ok;
  227.         }
  228.         else
  229.         {
  230.             *pwidth = width;
  231.             *pheight = height;
  232.  
  233.             Com_Printf ("failed\n" );
  234.  
  235.             Com_Printf ("...calling CDS assuming dual monitors:" );
  236.  
  237.             dm.dmPelsWidth = width * 2;
  238.             dm.dmPelsHeight = height;
  239.             dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
  240.  
  241.             if ( gl_bitdepth->value != 0 )
  242.             {
  243.                 dm.dmBitsPerPel = gl_bitdepth->value;
  244.                 dm.dmFields |= DM_BITSPERPEL;
  245.             }
  246.  
  247.             /*
  248.             ** our first CDS failed, so maybe we're running on some weird dual monitor
  249.             ** system 
  250.             */
  251.             if ( ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) != DISP_CHANGE_SUCCESSFUL )
  252.             {
  253.                 Com_Printf (" failed\n" );
  254.  
  255.                 Com_Printf ("...setting windowed mode\n" );
  256.  
  257.                 ChangeDisplaySettings( 0, 0 );
  258.  
  259.                 *pwidth = width;
  260.                 *pheight = height;
  261.                 gl_state.fullscreen = false;
  262.                 if ( !VID_CreateWindow (width, height, false) )
  263.                     return rserr_invalid_mode;
  264.                 return rserr_invalid_fullscreen;
  265.             }
  266.             else
  267.             {
  268.                 Com_Printf (" ok\n" );
  269.                 if ( !VID_CreateWindow (width, height, true) )
  270.                     return rserr_invalid_mode;
  271.  
  272.                 gl_state.fullscreen = true;
  273.                 return rserr_ok;
  274.             }
  275.         }
  276.     }
  277.     else
  278.     {
  279.         Com_Printf ("...setting windowed mode\n" );
  280.  
  281.         ChangeDisplaySettings( 0, 0 );
  282.  
  283.         *pwidth = width;
  284.         *pheight = height;
  285.         gl_state.fullscreen = false;
  286.         if ( !VID_CreateWindow (width, height, false) )
  287.             return rserr_invalid_mode;
  288.     }
  289.  
  290.     return rserr_ok;
  291. }
  292.  
  293. /*
  294. ** GLimp_Shutdown
  295. **
  296. ** This routine does all OS specific shutdown procedures for the OpenGL
  297. ** subsystem.  Under OpenGL this means NULLing out the current DC and
  298. ** HGLRC, deleting the rendering context, and releasing the DC acquired
  299. ** for the window.  The state structure is also nulled out.
  300. **
  301. */
  302. void GLimp_Shutdown( void )
  303. {
  304.     if ( qwglMakeCurrent && !qwglMakeCurrent( NULL, NULL ) )
  305.         Com_Printf ("ref_gl::R_Shutdown() - wglMakeCurrent failed\n");
  306.     if ( glw_state.hGLRC )
  307.     {
  308.         if (  qwglDeleteContext && !qwglDeleteContext( glw_state.hGLRC ) )
  309.             Com_Printf ("ref_gl::R_Shutdown() - wglDeleteContext failed\n");
  310.         glw_state.hGLRC = NULL;
  311.     }
  312.     if (glw_state.hDC)
  313.     {
  314.         if ( !ReleaseDC( glw_state.hWnd, glw_state.hDC ) )
  315.             Com_Printf ("ref_gl::R_Shutdown() - ReleaseDC failed\n" );
  316.         glw_state.hDC   = NULL;
  317.     }
  318.     if (glw_state.hWnd)
  319.     {
  320.         ShowWindow (glw_state.hWnd, SW_HIDE);
  321.         DestroyWindow (    glw_state.hWnd );
  322.         glw_state.hWnd = NULL;
  323.     }
  324.  
  325.     if ( glw_state.log_fp )
  326.     {
  327.         fclose( glw_state.log_fp );
  328.         glw_state.log_fp = 0;
  329.     }
  330.  
  331.     UnregisterClass (WINDOW_CLASS_NAME, glw_state.hInstance);
  332.  
  333.     if ( gl_state.fullscreen )
  334.     {
  335.         ChangeDisplaySettings( 0, 0 );
  336.         gl_state.fullscreen = false;
  337.     }
  338. }
  339.  
  340.  
  341. /*
  342. ** GLimp_Init
  343. **
  344. ** This routine is responsible for initializing the OS specific portions
  345. ** of OpenGL.  Under Win32 this means dealing with the pixelformats and
  346. ** doing the wgl interface stuff.
  347. */
  348. qboolean GLimp_Init( void *hinstance, void *wndproc )
  349. {
  350. #define OSR2_BUILD_NUMBER 1111
  351.  
  352.     OSVERSIONINFO    vinfo;
  353.  
  354.     vinfo.dwOSVersionInfoSize = sizeof(vinfo);
  355.  
  356.     glw_state.allowdisplaydepthchange = false;
  357.  
  358.     if ( GetVersionEx( &vinfo) )
  359.     {
  360.         if ( vinfo.dwMajorVersion > 4 )
  361.         {
  362.             glw_state.allowdisplaydepthchange = true;
  363.         }
  364.         else if ( vinfo.dwMajorVersion == 4 )
  365.         {
  366.             if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
  367.             {
  368.                 glw_state.allowdisplaydepthchange = true;
  369.             }
  370.             else if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
  371.             {
  372.                 if ( LOWORD( vinfo.dwBuildNumber ) >= OSR2_BUILD_NUMBER )
  373.                 {
  374.                     glw_state.allowdisplaydepthchange = true;
  375.                 }
  376.             }
  377.         }
  378.     }
  379.     else
  380.     {
  381.         Com_Printf ("GLimp_Init() - GetVersionEx failed\n" );
  382.         return false;
  383.     }
  384.  
  385.     glw_state.hInstance = ( HINSTANCE ) hinstance;
  386.     glw_state.wndproc = wndproc;
  387.  
  388.     return true;
  389. }
  390.  
  391. qboolean GLimp_InitGL (void)
  392. {
  393.     PIXELFORMATDESCRIPTOR pfd = 
  394.     {
  395.         sizeof(PIXELFORMATDESCRIPTOR),    // size of this pfd
  396.         1,                                // version number
  397.         PFD_DRAW_TO_WINDOW |            // support window
  398.         PFD_SUPPORT_OPENGL |            // support OpenGL
  399.         PFD_DOUBLEBUFFER,                // double buffered
  400.         PFD_TYPE_RGBA,                    // RGBA type
  401.         24,                                // 24-bit color depth
  402.         0, 0, 0, 0, 0, 0,                // color bits ignored
  403.         0,                                // no alpha buffer
  404.         0,                                // shift bit ignored
  405.         0,                                // no accumulation buffer
  406.         0, 0, 0, 0,                     // accum bits ignored
  407.         32,                                // 32-bit z-buffer    
  408.         0,                                // no stencil buffer
  409.         0,                                // no auxiliary buffer
  410.         PFD_MAIN_PLANE,                    // main layer
  411.         0,                                // reserved
  412.         0, 0, 0                            // layer masks ignored
  413.     };
  414.     int  pixelformat;
  415.     cvar_t *stereo;
  416.     
  417.     stereo = Cvar_Get( "cl_stereo", "0", 0 );
  418.  
  419.     /*
  420.     ** set PFD_STEREO if necessary
  421.     */
  422.     if ( stereo->value != 0 )
  423.     {
  424.         Com_Printf ("...attempting to use stereo\n" );
  425.         pfd.dwFlags |= PFD_STEREO;
  426.         gl_state.stereo_enabled = true;
  427.     }
  428.     else
  429.     {
  430.         gl_state.stereo_enabled = false;
  431.     }
  432.  
  433.     /*
  434.     ** figure out if we're running on a minidriver or not
  435.     */
  436.     if ( strstr( gl_driver->string, "opengl32" ) != 0 )
  437.         glw_state.minidriver = false;
  438.     else
  439.         glw_state.minidriver = true;
  440.  
  441.     /*
  442.     ** Get a DC for the specified window
  443.     */
  444.     if ( glw_state.hDC != NULL )
  445.         Com_Printf ("GLimp_Init() - non-NULL DC exists\n" );
  446.  
  447.     if ( ( glw_state.hDC = GetDC( glw_state.hWnd ) ) == NULL )
  448.     {
  449.         Com_Printf ("GLimp_Init() - GetDC failed\n" );
  450.         return false;
  451.     }
  452.  
  453.     if ( glw_state.minidriver )
  454.     {
  455.         if ( (pixelformat = qwglChoosePixelFormat( glw_state.hDC, &pfd)) == 0 )
  456.         {
  457.             Com_Printf ("GLimp_Init() - qwglChoosePixelFormat failed\n");
  458.             return false;
  459.         }
  460.         if ( qwglSetPixelFormat( glw_state.hDC, pixelformat, &pfd) == FALSE )
  461.         {
  462.             Com_Printf ("GLimp_Init() - qwglSetPixelFormat failed\n");
  463.             return false;
  464.         }
  465.         qwglDescribePixelFormat( glw_state.hDC, pixelformat, sizeof( pfd ), &pfd );
  466.     }
  467.     else
  468.     {
  469.         if ( ( pixelformat = ChoosePixelFormat( glw_state.hDC, &pfd)) == 0 )
  470.         {
  471.             Com_Printf ("GLimp_Init() - ChoosePixelFormat failed\n");
  472.             return false;
  473.         }
  474.         if ( SetPixelFormat( glw_state.hDC, pixelformat, &pfd) == FALSE )
  475.         {
  476.             Com_Printf ("GLimp_Init() - SetPixelFormat failed\n");
  477.             return false;
  478.         }
  479.         DescribePixelFormat( glw_state.hDC, pixelformat, sizeof( pfd ), &pfd );
  480.  
  481.         if ( !( pfd.dwFlags & PFD_GENERIC_ACCELERATED ) )
  482.         {
  483.             extern cvar_t *gl_allow_software;
  484.  
  485.             if ( gl_allow_software->value )
  486.                 glw_state.mcd_accelerated = true;
  487.             else
  488.                 glw_state.mcd_accelerated = false;
  489.         }
  490.         else
  491.         {
  492.             glw_state.mcd_accelerated = true;
  493.         }
  494.     }
  495.  
  496.     /*
  497.     ** report if stereo is desired but unavailable
  498.     */
  499.     if ( !( pfd.dwFlags & PFD_STEREO ) && ( stereo->value != 0 ) ) 
  500.     {
  501.         Com_Printf ("...failed to select stereo pixel format\n" );
  502.         Cvar_SetValue( "cl_stereo", 0 );
  503.         gl_state.stereo_enabled = false;
  504.     }
  505.  
  506.     /*
  507.     ** startup the OpenGL subsystem by creating a context and making
  508.     ** it current
  509.     */
  510.     if ( ( glw_state.hGLRC = qwglCreateContext( glw_state.hDC ) ) == 0 )
  511.     {
  512.         Com_Printf ( "GLimp_Init() - qwglCreateContext failed\n");
  513.         goto fail;
  514.     }
  515.  
  516.     if ( !qwglMakeCurrent( glw_state.hDC, glw_state.hGLRC ) )
  517.     {
  518.         Com_Printf ("GLimp_Init() - qwglMakeCurrent failed\n");
  519.         goto fail;
  520.     }
  521.  
  522.     if ( !VerifyDriver() )
  523.     {
  524.         Com_Printf ("GLimp_Init() - no hardware acceleration detected\n" );
  525.         goto fail;
  526.     }
  527.  
  528.     /*
  529.     ** print out PFD specifics 
  530.     */
  531.     Com_Printf ("GL PFD: color(%d-bits) Z(%d-bit)\n", ( int ) pfd.cColorBits, ( int ) pfd.cDepthBits );
  532.  
  533.     return true;
  534.  
  535. fail:
  536.     if ( glw_state.hGLRC )
  537.     {
  538.         qwglDeleteContext( glw_state.hGLRC );
  539.         glw_state.hGLRC = NULL;
  540.     }
  541.  
  542.     if ( glw_state.hDC )
  543.     {
  544.         ReleaseDC( glw_state.hWnd, glw_state.hDC );
  545.         glw_state.hDC = NULL;
  546.     }
  547.     return false;
  548. }
  549.  
  550. /*
  551. ** GLimp_BeginFrame
  552. */
  553. void GLimp_BeginFrame( float camera_separation )
  554. {
  555.     if ( gl_bitdepth->modified )
  556.     {
  557.         if ( gl_bitdepth->value != 0 && !glw_state.allowdisplaydepthchange )
  558.         {
  559.             Cvar_SetValue( "gl_bitdepth", 0 );
  560.             Com_Printf ("gl_bitdepth requires Win95 OSR2.x or WinNT 4.x\n" );
  561.         }
  562.         gl_bitdepth->modified = false;
  563.     }
  564.  
  565.     if ( camera_separation < 0 && gl_state.stereo_enabled )
  566.     {
  567.         qglDrawBuffer( GL_BACK_LEFT );
  568.     }
  569.     else if ( camera_separation > 0 && gl_state.stereo_enabled )
  570.     {
  571.         qglDrawBuffer( GL_BACK_RIGHT );
  572.     }
  573.     else
  574.     {
  575.         qglDrawBuffer( GL_BACK );
  576.     }
  577. }
  578.  
  579. /*
  580. ** GLimp_EndFrame
  581. ** 
  582. ** Responsible for doing a swapbuffers and possibly for other stuff
  583. ** as yet to be determined.  Probably better not to make this a GLimp
  584. ** function and instead do a call to GLimp_SwapBuffers.
  585. */
  586. void GLimp_EndFrame (void)
  587. {
  588.     int        err;
  589.  
  590.     err = qglGetError();
  591.     assert( err == GL_NO_ERROR );
  592.  
  593.     if ( stricmp( gl_drawbuffer->string, "GL_BACK" ) == 0 )
  594.     {
  595.         if ( !qwglSwapBuffers( glw_state.hDC ) )
  596.             Com_Error( ERR_FATAL, "GLimp_EndFrame() - SwapBuffers() failed!\n" );
  597.     }
  598. }
  599.  
  600. /*
  601. ** GLimp_AppActivate
  602. */
  603. void GLimp_AppActivate( qboolean active )
  604. {
  605.     if ( active )
  606.     {
  607.         SetForegroundWindow( glw_state.hWnd );
  608.         ShowWindow( glw_state.hWnd, SW_RESTORE );
  609.     }
  610.     else
  611.     {
  612.         if ( vid_fullscreen->value )
  613.             ShowWindow( glw_state.hWnd, SW_MINIMIZE );
  614.     }
  615. }
  616.